/*
 * Copyright (C) 2012 Tomas Shestakov. <http://code.google.com/p/jmmo/>
 */

package jmmo.engine.event

import jmmo.util.requireNonNull

object EventType {
  /**
   * The parent type of all types of events.
   */
  val Root = new EventType[TypedEvent]
  /**
   * The name for types with not specified names
   */
  protected val NoName = "Noname"
  /**
   * Creates instance of the EventType with specified name and `EventType.Root` as super type
   * @param name name of the EventType
   * @tparam A event class to which this type of
   * @return new instance of the EventType class
   */
  def apply[A <: TypedEvent](name: String) = new EventType[A](name)
  /**
   * Creates instance of the EventType with specified super type and `EventType.NoName` as name.
   * @param superType super type of the EventType
   * @tparam A event class to which this type of
   * @return new instance of the EventType class
   */
  def apply[A <: TypedEvent](superType: EventType[_ >: A <: TypedEvent]) = new EventType[A](superType)
}

/**
 * Type for typed events.
 * The event type provides additional classification to events of the same Event class.
 * Contains the type name and the super type.
 * By subscribing to the parent type of event you will receive events of child types.
 * The oldest type of parent is `EventType.Root`.
 * <p></p>
 * Тип для типизированных событий.
 * Содержит имя типа и родительский тип.
 * Подписавшись на родительский тип события будешь получать события дочерних типов.
 * Самый старший родительский тип `EventType.Root`.
 * @param name name of the EventType
 * @param superType super type of the EventType
 * @tparam A event class to which this type of
 * @author Tomas Shestakov
 */
case class EventType[-A <: TypedEvent](name: String, superType: EventType[_ >: A <: TypedEvent]) {
  requireNonNull(name, "EventType name cannot be null")
  requireNonNull(superType, "EventType superType cannot be null")

  /**
   * Creates instance of the EventType with specified name and `EventType.Root` as super type
   * @param name name of the EventType
   */
  def this(name: String) = this(name, EventType.Root)
  /**
   * Creates instance of the EventType with specified super type and `EventType.NoName` as name.
   * @param superType super type of the EventType
   */
  def this(superType: EventType[_ >: A <: TypedEvent]) = this(EventType.NoName, superType)
  /**
   * Creates root instance of all EventType's.
   * Only use to create `EventType.Root` constant.
   */
  private def this() = this("Root", null)
}
